package com.polaris.live.ui.live.fragment

import android.app.Activity
import android.os.Bundle
import android.view.View
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.StringUtils
import com.blankj.utilcode.util.TimeUtils
import com.blankj.utilcode.util.Utils
import com.gyf.immersionbar.ImmersionBar
import com.lxj.xpopup.XPopup
import com.polaris.live.R.drawable
import com.polaris.live.cache.CommonCache
import com.polaris.live.common.ext.convertArabicDigitsToNormal
import com.polaris.live.common.ext.setOnSingleClickListener
import com.polaris.live.common.mvvm.base2.BaseVbFragment
import com.polaris.live.common.network.parseState
import com.polaris.live.common.util.DateUtils
import com.polaris.live.common.util.NavigationBarUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.constant.LiveConst
import com.polaris.live.constant.UserConst
import com.polaris.live.databinding.FragmentJustStartBinding
import com.polaris.live.dialog.AwardProgressDialog
import com.polaris.live.dialog.GlobalDialogManager
import com.polaris.live.dialog.LiveHangUpDialog
import com.polaris.live.im.manager.ImLiveManager
import com.polaris.live.im.sfs.COMMAND_LIVE_CLOSE
import com.polaris.live.im.sfs.LIVE_NEW_ANCHOR
import com.polaris.live.im.sfs.LIVE_UPLOAD_FACE
import com.polaris.live.im.sfs.LIVE_WARN_MESSAGE
import com.polaris.live.im.sfs.bean.live.CallSignalingMessage
import com.polaris.live.im.sfs.bean.live.LiveRoomInfo
import com.polaris.live.im.sfs.bean.live.SendLiveCloseMessage
import com.polaris.live.im.sfs.bean.live.payload.NewAnchorSubsidyPayloadBean
import com.polaris.live.manager.LiveStateManager
import com.polaris.live.popup.GameListPopup
import com.polaris.live.popup.GlobalPopupManager
import com.polaris.live.popup.WeeklyStarPopup
import com.polaris.live.resp.back_resp.LiveSubsidyIndicatorResp
import com.polaris.live.resp.back_resp.ScreenshotStrategyVo
import com.polaris.live.resp.event.BackgroundEvent
import com.polaris.live.translation.R
import com.polaris.live.ui.game.GameUtils
import com.polaris.live.ui.live.proxy.LiveMoreProxy
import com.polaris.live.ui.live.proxy.LivePublicProxy
import com.polaris.live.ui.live.widget.OnLiveAnswerListener
import com.polaris.live.ui.live.widget.listener.OnBackPressedListener
import com.polaris.live.ui.live.widget.listener.OnChangeCameraListener
import com.polaris.live.ui.live.widget.listener.OnLiveCallCallback
import com.polaris.live.ui.live.widget.listener.OnLiveEventListener
import com.polaris.live.ui.live.widget.listener.OnLiveNetworkListener
import com.polaris.live.ui.live.widget.listener.OnLiveStateSwitchListener
import com.polaris.live.ui.main.live.LiveFragment
import com.polaris.live.ui.message.fragment.dialog.MessageSessionDialogFragment
import com.polaris.live.utils.LiveUtils
import com.polaris.live.utils.route.RoutePath
import com.polaris.live.utils.route.Router
import com.polaris.live.utils.zego.LiveEngineManage
import com.polaris.live.utils.zego.beauty.OnFaceStateChangeListener
import com.polaris.live.viewmodel.live.LiveVideoViewModel
import im.zego.zegoexpress.callback.IZegoEventHandler
import im.zego.zegoexpress.entity.ZegoPlayStreamQuality
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

/**
 * 坐等页面
 *
 * @author Created by 半仙 on 2023/9/26/026 21:04
 */
class LiveMatchFragment : BaseVbFragment<LiveVideoViewModel, FragmentJustStartBinding>(),
    OnBackPressedListener,
    OnLiveStateSwitchListener,
    OnFaceStateChangeListener,
    OnLiveEventListener,
    OnLiveNetworkListener,
    OnChangeCameraListener {

    private val mLiveInfo by lazy {
        arguments?.getParcelable<LiveRoomInfo>(LiveConst.Params.LIVE_INFO)
            ?: throw IllegalArgumentException("liveInfo is null")
    }
    private val mScreenshotStrategy by lazy {
        arguments?.getParcelable<ScreenshotStrategyVo>(LiveConst.Params.SCREENSHOT_STRATEGY)
    }

    private val mSessionFragment by lazy { MessageSessionDialogFragment() }

    private val mLiveMoreProxy by lazy {
        LiveMoreProxy(
            requireContext(), this, mViewModel,
            pageType,
            this,
            this
        )
    }
    private val mLivePublicProxy by lazy {
        LivePublicProxy(requireContext(), mViewModel)
    }

    private val mEventHandler = object : IZegoEventHandler() {
        override fun onPlayerQualityUpdate(streamID: String?, quality: ZegoPlayStreamQuality?) {
            super.onPlayerQualityUpdate(streamID, quality)
            if (quality?.level in LiveStateManager.USER_LIVE_STATE_BAD) {
                mBinding.llSignal.visibility = View.VISIBLE
            } else {
                mBinding.llSignal.visibility = View.GONE
            }
        }
    }

    private val mOnAppStatusChangedListener = object : Utils.OnAppStatusChangedListener {
        override fun onForeground(activity: Activity?) {
            mViewModel.stopKillActivityTimeout()
        }

        override fun onBackground(activity: Activity?) {
            mViewModel.killActivityTimeout(maxBackgroundTime)
        }
    }

    private var mLiveHangUpDialog: LiveHangUpDialog? = null

    private var mOnLiveCallCallback: OnLiveCallCallback? = null
    private var mOnLiveAnswerListener: OnLiveAnswerListener? = null

    private var mPauseLiving: Boolean = false
    private var mStopLive: Boolean = false

    private var mSubsidy: LiveSubsidyIndicatorResp? = null

    private var lastIndex = 3
    private fun initImmersionBar() {
        ImmersionBar.with(this)
            .transparentBar()
            .titleBarMarginTop(mBinding.rlContent)
            .init()

        NavigationBarUtils.setNavigationHeight(mBinding.rlContent)
    }

    override fun initView(savedInstanceState: Bundle?) {
        initImmersionBar()
        EventBus.getDefault().register(this)
        LiveEngineManage.eventHandlerHelper.addEventHandler(mEventHandler)
        //UI初始化
        mBinding.apply {
            vHeader.initData(pageType, mLiveInfo, 1)
            vFooter.initUI(pageType, mViewModel)
            vFooter.initData(mLiveInfo)
        }
        val liveResource = CommonCache.getLiveResource()
        if (liveResource != null) {
            when (liveResource.liveSubsidy) {
                LiveFragment.SUBSIDT_SHOW -> mBinding.ivLookAnchor.visibility = View.GONE
                LiveFragment.SUBSIDY_OPEN -> mBinding.ivLookAnchor.visibility = View.VISIBLE
                LiveFragment.SUBSIDY_CLOSE -> mBinding.ivLookAnchor.visibility = View.VISIBLE
            }
        } else {
            mBinding.ivLookAnchor.visibility = View.GONE
        }
        mViewModel.getSubsidy()
        initObserve()
        initListener()
    }

    private fun initListener() {
        mBinding.apply {
            /**
             * 展示详情弹窗
             */
            weekStar.setShowDetail {
                WeeklyStarPopup.showPop(requireContext(), this@LiveMatchFragment, mViewModel, lastIndex) {
                    lastIndex = it
                }
            }
            /**
             * 周星是否显示数据
             */
            weekStar.setShowWeekStarCallBack {
                if (it) {
                    mViewModel.pollingWeeklyStarRank()
                } else {
                    mViewModel.cancelPollingWeeklyStarRank()
                }
            }

            //点击主播头像
            vHeader.setOnAvatarClientListener {
                showUserProfilePopup(mLiveInfo.userId)
            }
            vFooter.setOnMessageClickListener {
                mSessionFragment.show(
                    childFragmentManager,
                    MessageSessionDialogFragment.FRAGMENT_TAG
                )
            }
            vFooter.setOnMoreClickListener {
                mLiveInfo.liveId.let { it1 -> mLiveMoreProxy.showVideoMore(objectId = it1) }
            }
            vFooter.setOnGameClickListener {
                GameListPopup.show(
                    requireContext(),
                    GameUtils.getLiveCacheGameList(),
                    mLiveInfo.userId.toString()
                )
            }
            avAnswer.setOnLiveAnswerListener(object : OnLiveAnswerListener {
                override fun onAnswer(message: CallSignalingMessage, needLoading: Boolean) {
                    mOnLiveAnswerListener?.onAnswer(message, needLoading)
                }

                override fun onRefuse(message: CallSignalingMessage, type: Int) {
                    mOnLiveAnswerListener?.onRefuse(message, type)
                }
            })
            ivLookAnchor.setOnSingleClickListener {
                mViewModel.getSubsidy()
            }
        }

    }

    private fun initObserve() {
        AppUtils.registerAppStatusChangedListener(mOnAppStatusChangedListener)
        /**
         * 周星数据更新
         */
        mViewModel.weeklyStarRankData.observe(this) { state ->
            parseState(state, {
                if (it.show) {
                    mViewModel.cancelPollingWeeklyStarRank()
                    mBinding.weekStar.visibility = View.VISIBLE
                    it.base?.let { da ->
                        mBinding.weekStar.setData(da)
                    }
                } else {
                    mViewModel.pollingWeeklyStarRank()
                    mBinding.weekStar.visibility = View.GONE
                }
            }, {
                //报错开启定时请求
                mViewModel.pollingWeeklyStarRank()
            })
        }

        //停止直播
        mViewModel.stopLiveLiveData.observe(this) { state ->
            parseState(state, {
                Router.builder(RoutePath.LIVE_END_ANCHOR_ACTIVITY)
                    .withInt(LiveConst.Params.LIVE_TYPE, mLiveInfo.type)
                    .withAny(LiveConst.Params.LIVE_END_INFO, it)
                    .navigation(requireActivity())
            }, {
                ToastGravity.showGravity(it.message)
            })
            requireActivity().finish()
        }
        //恢复直播间失败
        mViewModel.recoverFailureLiveData.observe(this) {
            onStopLive()
        }
        //获取游戏列表
        mViewModel.gameLiveData.observe(this) { resultState ->
            parseState(resultState, {
                mBinding.vFooter.updateGameState(it.isNotEmpty())
                GameUtils.setLiveCacheGameList(it)
            })
        }
        //人脸
        mViewModel.faceStateLiveData.observe(this) {
            if (it == -2) {
                onStopLive()
            } else if (it == -1) {
                mBinding.llDark.visibility = View.GONE
            } else {
                mBinding.llDark.visibility = View.VISIBLE
                mBinding.icBotton.text = "${it / 1000}"
            }
        }
        //心跳
        mViewModel.liveHeartbeatLiveData.observe(this) {
            if (it) {
                onStopLive()
            }
        }
        //计时
        mViewModel.timerLiveData.observe(this) {
            val millis2String = DateUtils.minuteSChangeTime(it)
            mBinding.trialTime.text = "${millis2String.convertArabicDigitsToNormal()}"
            mBinding.llTrial.visibility = View.VISIBLE
        }
        //试播
        mViewModel.trialCountdownLiveData.observe(this) {
            if (it == -1L) {
                mBinding.llTrial.visibility = View.GONE
                mBinding.timerImg.setImageResource(drawable.ic_timer)
                mViewModel.timerdown(mLiveInfo.startTime)
            } else {
                val millis2String = TimeUtils.millis2String(it, "mm:ss")
                mBinding.trialTime.text =
                    "${StringUtils.getString(R.string.trail_time)} ${millis2String.convertArabicDigitsToNormal()}"
                mBinding.llTrial.visibility = View.VISIBLE
            }
        }
        //直播关闭消息，如果直播接收到消息，说明服务器关闭了直播
        ImLiveManager.observe(this, { mLiveInfo.liveId }) {
            withMessage<SendLiveCloseMessage>(COMMAND_LIVE_CLOSE) {
                onStopLive()
            }
        }
        //直播公屏消息
        ImLiveManager.observePublicMessage(this, { mLiveInfo.liveId }, { message ->
            //其他消息处理
            when (message.type) {
                //警告消息
                LIVE_WARN_MESSAGE -> {
                    mLivePublicProxy.onPublicMessage(message)
                }
                //人脸截图上报
                LIVE_UPLOAD_FACE -> {
                    mViewModel.facesDetect(mLiveInfo.liveId)
                }

                //新主播补贴消息
                LIVE_NEW_ANCHOR -> {
                    val payload = message.payload as NewAnchorSubsidyPayloadBean
                    GlobalDialogManager.showNewLiveAnchor(requireContext(), payload)
                }
            }
        })
        mViewModel.mSubsidyLiveData.observe(this) { resultState ->
            parseState(resultState, {
                if (mSubsidy == null) {
                    mSubsidy = it
                } else {
                    mSubsidy = it
                    if (it.show) {
                        XPopup.Builder(requireContext())
                            .isDestroyOnDismiss(true)
                            .asCustom(AwardProgressDialog(requireContext(), it))
                            .show()
                    } else {
                        mBinding.ivLookAnchor.visibility = View.GONE
                    }
                }
            })
        }
    }

    override fun initData() {
        mViewModel.getGameList(mLiveInfo.liveId)  //游戏列表

        //默认总是直播所以这里可以直接开始
        onLiveResume()
    }

    override fun onLivePause() {
        withLoaded {
            invokeOnLivePause()
        }

        mPauseLiving = true
    }

    private fun invokeOnLivePause() {
        mViewModel.resetLiveJob()
    }

    override fun onLiveResume() {
        /**
         * 坐等获取周星数据
         */
        if (mLiveInfo.type == LiveConst.Type.ONLY_MATCH) {
            mViewModel.getWeeklyStarRank()
        }

        mViewModel.launchLiveHeartbeat(mLiveInfo.liveId) //心跳
        //试播
        mLiveInfo.trialTime?.also {
            mViewModel.launchTrialCountdown(it)
        }
        //截图
        LiveUtils.resolveScreenshotStrategy(pageType, mScreenshotStrategy)?.also {
            mViewModel.launchScreenshot(pageType, mLiveInfo.liveId, mLiveInfo.startTime, it)
        }
        //开播先认为没有人脸
        mViewModel.triggerFaceChange(showFace = false, init = true)

        mPauseLiving = false
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        if (hidden) {
            mLiveHangUpDialog?.dismiss()
            mLiveHangUpDialog = null
        }
    }

    private fun showUserProfilePopup(userId: Long) {
        GlobalPopupManager.showUserProfilePopup(
            requireContext(), this, mViewModel,
            userId, UserConst.From.LIVE, mLiveInfo.liveId
        )
    }

    override fun onFaceStateChange(valid: Boolean) {
        withLoaded {
            triggerFaceChange(valid)
        }
    }

    private fun triggerFaceChange(valid: Boolean, init: Boolean = false) {
        if (mPauseLiving) {
            return
        }

        mViewModel.triggerFaceChange(valid, init)
    }

    /**
     * 来电
     */
    override fun onLivingToCall(callBean: CallSignalingMessage) {
        if (mPauseLiving) {
            return
        }

        withLoaded {
            mBinding.avAnswer.onLivingToCall(callBean)
        }
    }

    override fun onCancelToCall(callBean: CallSignalingMessage) {
        withLoaded {
            mBinding.avAnswer.onCancelToCall(callBean)
        }
    }

    override fun onNetwork(isNetwork: Boolean, isConnected: Boolean) {
        //这里不管是否连接，都直接恢复，重复调用不会出错
        withLoaded {
            //如果上次是断开连接，这次连接上了，需要重连
            if (!mBinding.vNetwork.isConnected && isConnected) {
                onRecoverLive()
            }

            mBinding.vNetwork.setNetworkState(isNetwork, isConnected)
        }
    }

    override fun onChangeCamera() {
        mOnLiveCallCallback?.onChangeCamera()
    }

    override fun setOnLiveCallCallback(l: OnLiveCallCallback) {
        mOnLiveCallCallback = l
    }

    override fun setOnLiveAnswerListener(l: OnLiveAnswerListener) {
        mOnLiveAnswerListener = l
    }

    override fun onRecoverLive() {
        withLoaded {
            mViewModel.recoverLive()
        }
    }

    private fun onStopLive(needLoading: Boolean = false) {
        if (mStopLive) {
            return
        }

        mViewModel.stopLive(mLiveInfo.liveId, needLoading)

        mStopLive = true
    }

    override fun onBackPressed(): Boolean {
        if (!isCreated() || activity?.isFinishing != false) {
            return true
        }

        mLiveHangUpDialog = LiveHangUpDialog.showDialog(
            requireContext(),
            mLiveHangUpDialog,
            mLiveInfo,
            mSubsidy
        ) {
            onStopLive(it)
        }

        return true
    }

    override fun onDestroyView() {
        super.onDestroyView()

        LiveEngineManage.eventHandlerHelper.removeEventHandler(mEventHandler)

        mLiveHangUpDialog?.dismiss()
        mLiveHangUpDialog = null
    }

    override fun onDestroy() {
        super.onDestroy()
        EventBus.getDefault().unregister(this)
        AppUtils.unregisterAppStatusChangedListener(mOnAppStatusChangedListener)

        if (isCreated()) {
            mViewModel.stopKillActivityTimeout()
        }
    }

    /**
     * 在后台计时到
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onBackGroundEvent(event: BackgroundEvent) {
        onStopLive()
    }

    companion object {

        private const val pageType = LiveConst.Page.LIVE_MATCH

        private const val maxBackgroundTime = 30000L //主播在后台停留挂断事件
    }
}